import serial
import time

class LingkongMotor:
    # 新增 ser 参数，允许传入外部串口实例
    def __init__(self, port='COM3', baudrate=115200, motor_id=0x01, ser=None):
        self.motor_id = motor_id
        self.low_speed = 20  # 低速参数（度/秒）
        self.zero_angle_target = 0

        # 优先使用外部传入的串口实例（共享模式）
        if ser is not None:
            self.ser = ser
            # 验证波特率匹配
            if self.ser.baudrate != baudrate:
                raise ValueError(f"共享串口波特率({self.ser.baudrate})与电机要求({baudrate})不一致")
        else:
            # 独立模式：自己创建串口
            self.ser = serial.Serial(
                port=port,
                baudrate=baudrate,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                bytesize=serial.EIGHTBITS,
                timeout=0.5
            )

    def calc_checksum(self, data):
        return sum(data) & 0xFF

    def send_command(self, cmd, data_bytes=b''):
        """发送命令（保持原有逻辑）"""
        frame_cmd = [0x3E, cmd, self.motor_id, len(data_bytes)]
        frame_cmd_checksum = self.calc_checksum(frame_cmd)
        frame_cmd.append(frame_cmd_checksum)
        full_frame = bytes(frame_cmd) + data_bytes
        if data_bytes:
            data_checksum = self.calc_checksum(data_bytes)
            full_frame += bytes([data_checksum])
        self.ser.write(full_frame)
        time.sleep(0.001)
        return self.ser.read(32)

    # 以下方法（read_current_multi_turn_angle、move_to_multi_turn_zero等）保持不变
    def read_current_multi_turn_angle(self):
        response = self.send_command(0x92)
        if len(response) >= 14:
            angle_bytes = response[5:13]
            current_angle = int.from_bytes(angle_bytes, byteorder='little', signed=True)
            current_angle_deg = current_angle * 0.01
            return current_angle, current_angle_deg
        else:
            print("读取当前多圈角度失败，响应不完整")
            return None, None

    def move_to_multi_turn_zero(self):
        print(f"开始返回多圈0位（目标角度：0.00°），速度：{self.low_speed}度/秒")
        target_angle_bytes = self.zero_angle_target.to_bytes(8, byteorder='little', signed=True)
        max_speed_value = int(self.low_speed * 100)
        speed_bytes = max_speed_value.to_bytes(4, byteorder='little', signed=False)
        data_bytes = target_angle_bytes + speed_bytes
        self.send_command(0xA4, data_bytes)

        wait_count = 0
        max_wait_seconds = 300
        while True:
            current_angle, current_angle_deg = self.read_current_multi_turn_angle()
            if current_angle is None:
                time.sleep(1)
                wait_count += 1
                if wait_count > max_wait_seconds:
                    print("等待返回0位超时，可能存在故障")
                    return False
                continue
            if abs(current_angle - self.zero_angle_target) <= 10:
                print(f"已到达多圈0位！当前角度：{current_angle_deg:.2f}°")
                return True
            else:
                print(f"正在靠近0位...当前角度：{current_angle_deg:.2f}°", end='\r')
                time.sleep(1)
                wait_count += 1
                if wait_count > max_wait_seconds:
                    print(f"\n等待返回0位超时（超过{max_wait_seconds}秒）")
                    return False

    def rotate_360_from_zero(self):
        target_angle = 36000
        print(f"\n开始从0位旋转360度，目标角度：360.00°，速度：{self.low_speed}度/秒")
        target_angle_bytes = target_angle.to_bytes(8, byteorder='little', signed=True)
        max_speed_value = int(self.low_speed * 100)
        speed_bytes = max_speed_value.to_bytes(4, byteorder='little', signed=False)
        data_bytes = target_angle_bytes + speed_bytes
        self.send_command(0xA4, data_bytes)

        wait_count = 0
        max_wait_seconds = 300
        while True:
            current_angle, current_angle_deg = self.read_current_multi_turn_angle()
            if current_angle is None:
                time.sleep(1)
                wait_count += 1
                if wait_count > max_wait_seconds:
                    print("旋转360度超时")
                    return False
                continue
            if abs(current_angle - target_angle) <= 10:
                print(f"已完成360度旋转！当前角度：{current_angle_deg:.2f}°")
                return True
            else:
                print(f"旋转中...当前角度：{current_angle_deg:.2f}°", end='\r')
                time.sleep(1)
                wait_count += 1
                if wait_count > max_wait_seconds:
                    print(f"\n旋转360度超时（超过{max_wait_seconds}秒）")
                    return False

    def close(self):
        """关闭串口（共享模式下不关闭）"""
        # 如果是独立创建的串口则关闭，共享的串口由外部管理
        if hasattr(self, 'ser') and self.ser.is_open and not hasattr(self, 'external_ser'):
            self.ser.close()
            print("电机串口已关闭")